import * as THREE from 'three'
import { huanJing } from '../huanJing/HuanJing.js'

function UUIDv4() {
	return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
		var r = Math.random() * 16 | 0;
		var v = c === 'x' ? r : (r & 0x3 | 0x8);
		return v.toString(16);
	})
}

// 完整地址
let wanZhengDiZhi = new Function('diZhi', `
	return new URL(diZhi, self.location.href).href
`)

// 本地向量转为世界向量（就是只应用旋转矩阵）
function benDiXiangLiangZhuanShiJie(xiangLiang, shiJieJuZhen) {
	const x = xiangLiang.x, y = xiangLiang.y, z = xiangLiang.z;
	const e = shiJieJuZhen.elements;
	xiangLiang.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
	xiangLiang.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
	xiangLiang.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
	
	return xiangLiang
}
// 页面坐标转相机坐标
function yeMianZhuanXiangJiZuoBiao(x, y) {
	return [( x / huanJing.width ) * 2 - 1, - ( y / huanJing.height ) * 2 + 1]
}
// 相机转页面坐标
function xiangJiZhuangYeMianZuoBiao(x, y) {
	return [Math.round((x + 1) * huanJing.width / 2), Math.round((1 - y) * huanJing.height / 2)]
}

// 测两网格对象世界坐标下距离
function ceShiJieJuLi(a, b) {
	let aWeiZhi = new THREE.Vector3()
	let bWeiZhi = new THREE.Vector3()
	a.updateWorldMatrix(true)
	b.updateWorldMatrix(true)
	aWeiZhi.setFromMatrixPosition(a.matrixWorld)
	bWeiZhi.setFromMatrixPosition(b.matrixWorld)
	return aWeiZhi.distanceTo(bWeiZhi)
}

// 点精灵文字纹理
// 射线检测到的sprite是正方形区域会比看到的大
function wenBenWenLi_(wenZi) {
	// 方案1
	let huaBuChiCun = 256
	let bianJu = 4
	let neiChiCun = huaBuChiCun - bianJu * 2
	let ziGao = 16
	let hangGao = 18
	let huaBu = document.createElement('canvas')
	huaBu.setAttribute('width', huaBuChiCun)
	huaBu.setAttribute('height', huaBuChiCun)
	let ctx = huaBu.getContext('2d')
	ctx.font = `normal ${ziGao}px math`;
	let zongChang = ctx.measureText(wenZi).width // 文字总长度
	let hangShu = Math.ceil(zongChang / neiChiCun)
	let hangKuan = Math.min(zongChang, neiChiCun)
	let x = huaBuChiCun / 2
	let y = huaBuChiCun - (hangShu - 1) * hangGao - bianJu
	
	ctx.imageSmoothingEnabled = true
	ctx.filter = 'moz-crispimage';
	ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'
	ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)'
	let beiJingX = x - hangKuan / 2 - bianJu
	let beiJingY = y - hangGao - bianJu
	let beiJingKuan = hangKuan + bianJu * 2
	let beiJingGao = hangShu * hangGao + bianJu * 2
	ctx.fillRect(beiJingX, beiJingY, beiJingKuan, beiJingGao)
	ctx.strokeRect(beiJingX, beiJingY, beiJingKuan, beiJingGao)
	ctx.textAlign = 'center'
	ctx.fillStyle = '#fff'
	ctx.textBaseline = 'bottom';
	let ziFu = ''
	for(let i = 0; i < wenZi.length; i++) {
		let yuCeZiFu = ziFu + wenZi[i]
		let ziKuan = ctx.measureText(yuCeZiFu).width
		if (ziKuan > neiChiCun) {
			ctx.fillText(ziFu, x, y);
			ziFu = wenZi[i]
			y += hangGao
		} else ziFu = yuCeZiFu
	}
	ctx.fillText(ziFu, x, y);
	const wenLi = new THREE.TextureLoader().load(huaBu.toDataURL());  // toDataURL会卡顿
	wenLi.colorSpace = THREE.SRGBColorSpace // 人眼舒适颜色
	return wenLi
}

function wenBenWenLi(wenZi) {
	// 方案2 html->svg->图片
	let chiCun = 256
	let ziGao = 16
	let rongQiDiv = document.createElement('div')
	rongQiDiv.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
	rongQiDiv.style = `width: ${chiCun}px; height: ${chiCun}px; display: flex;justify-content: center; align-items: flex-end;`
	
	let wenZiDiv = document.createElement('div')
	wenZiDiv.innerHTML = wenZi
	wenZiDiv.style.setProperty('font-size', `${ziGao}px`)
	wenZiDiv.style.setProperty('text-align', `center`)
	wenZiDiv.style.setProperty('color', `#fff`)
	wenZiDiv.style.setProperty('background', `rgba(0, 0, 0, 8)`)
	wenZiDiv.style.setProperty('border', `1px ridge rgba(255, 255, 255, 0.8)`)
	wenZiDiv.style.setProperty('padding', `0 4px`)
	wenZiDiv.style.setProperty('border-radius', `5px`)
	
	rongQiDiv.appendChild(wenZiDiv)
	
	var htmlSvg = `data:image/svg+xml;charset=utf-8,
		<svg xmlns="http://www.w3.org/2000/svg" width="${chiCun}" height="${chiCun}">
			<foreignObject x="0" y="0" width="100%" height="100%">
				${new XMLSerializer().serializeToString(rongQiDiv)}
			</foreignObject>
		</svg>
	`;
	htmlSvg = htmlSvg.replace(/\n/g, '').replace(/\t/g, '').replace(/#/g, '%23');
	let wenLi = new THREE.TextureLoader().load(htmlSvg);
	wenLi.colorSpace = THREE.SRGBColorSpace // 人眼舒适颜色
	return wenLi
}

class XinXiKuang {
	wenBen = ''
	dianJingLing = null
	xinXiKuangDieDai = null
	
	constructor() {
		this.xinXiKuangDieDai = this.mingZiKuang()
	}
	
	async *mingZiKuang() {
		const caiZhi = new THREE.SpriteMaterial( { map: new THREE.Texture(), depthTest: false, sizeAttenuation: false } )
		const dianJingLing = new THREE.Sprite( caiZhi )
		dianJingLing.scale.set( 1, 1, 1 )
		dianJingLing.center.set(0.5, 0)
		this.dianJingLing = dianJingLing
		let mingZi = new THREE.LOD()
		mingZi.addLevel(dianJingLing, 0)
		// mingZi.addLevel(new THREE.Object3D(), 1000)
	
		while (true) {
			caiZhi.map.dispose()
			caiZhi.map = await wenBenWenLi(this.wenBen)
			caiZhi.needsUpdate = true // 异步必须更新才生效
			yield
		}
	}
	xianShi(wenBen, weiZhi) {
		this.wenBen = wenBen
		this.xinXiKuangDieDai.next()
		this.dianJingLing.position.copy(weiZhi)
		huanJing.scene.add(this.dianJingLing)
	}
	yinCang() {
		if (this.dianJingLing) huanJing.scene.remove(this.dianJingLing)
	}
}

export {
	UUIDv4,
	wanZhengDiZhi,
	benDiXiangLiangZhuanShiJie,
	yeMianZhuanXiangJiZuoBiao,
	xiangJiZhuangYeMianZuoBiao,
	ceShiJieJuLi,
	wenBenWenLi,
	XinXiKuang
}